#include "SceneViewer.hpp"
#include <QtMath>

#include <QDebug>

SceneViewer::SceneViewer(QWidget *parent)
    : QGraphicsView(parent)
{
    setRenderHint(QPainter::Antialiasing, false);
    setDragMode(QGraphicsView::RubberBandDrag);
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
}

void SceneViewer::setGridVisible(bool visible)
{
    if (m_gridVisible != visible)
    {
        m_gridVisible = visible;
        viewport()->update(); // 触发重绘
    }
}

void SceneViewer::setGridStyle(const QColor &majorColor, const QColor &minorColor, int majorSpacing, int minorSpacing,
                               int lineWidth)
{
    m_majorGridColor = majorColor;
    m_minorGridColor = minorColor;
    m_majorGridSpacing = qMax(10, majorSpacing); // 最小间距10像素
    m_minorGridSpacing = qMax(5, minorSpacing); // 最小间距5像素
    m_gridLineWidth = qBound(1, lineWidth, 5); // 线宽限制在1-5像素

    // 确保次网格间距是主网格间距的约数
    if (m_majorGridSpacing % m_minorGridSpacing != 0)
    {
        m_minorGridSpacing = m_majorGridSpacing / 4; // 默认设为1/4
    }

    viewport()->update();
}

void SceneViewer::setGridDensity(int density)
{
    m_gridDensity = qBound(1, density, 5); // 密度系数1-5
    viewport()->update();
}

bool SceneViewer::isGridVisible() const
{
    return m_gridVisible;
}

void SceneViewer::drawBackground(QPainter *painter, const QRectF &rect)
{
    // 先调用基类绘制默认背景
    QGraphicsView::drawBackground(painter, rect);

    if (m_gridVisible)
    {
        drawGrid(painter, rect);
    }
}

void SceneViewer::wheelEvent(QWheelEvent *event)
{
    // Ctrl+滚轮实现缩放
    QPoint numDegrees = event->angleDelta() / 8;

    if (!numDegrees.isNull())
    {
        QPoint numSteps = numDegrees / 15;
        double scaleFactor = qPow(1.2, numSteps.y());

        // 限制缩放范围
        qreal currentScale = transform().m11();
        if ((scaleFactor > 1.0 && currentScale < 10.0) ||
            (scaleFactor < 1.0 && currentScale > 0.1))
        {
            scale(scaleFactor, scaleFactor);
            m_currentScale = transform().m11();
            qDebug() << m_currentScale;
            // 触发重绘以更新网格
            viewport()->update();
        }
    }
    event->accept();
}

void SceneViewer::drawGrid(QPainter *painter, const QRectF &rect)
{
    painter->save();
    painter->setRenderHint(QPainter::Antialiasing, false);

    // 计算有效的网格间距（考虑缩放因子）
    qreal effectiveMajorSpacing = calculateEffectiveSpacing(m_majorGridSpacing);
    qreal effectiveMinorSpacing = calculateEffectiveSpacing(m_minorGridSpacing);

    // 获取需要重绘的区域边界
    qreal left = rect.left();
    qreal top = rect.top();
    qreal right = rect.right();
    qreal bottom = rect.bottom();
    // 计算起始位置（对齐到网格）
    qreal startX = qFloor(left / effectiveMinorSpacing) * effectiveMinorSpacing;
    qreal startY = qFloor(top / effectiveMinorSpacing) * effectiveMinorSpacing;
    if (m_currentScale >= 0.5)
    {
        // 只绘制主网格，不绘制次网格
        // 绘制垂直次网格线
        // 绘制次网格（较细、较浅）
        QPen minorPen(m_minorGridColor, m_gridLineWidth, Qt::DotLine);
        painter->setPen(minorPen);

        for (qreal x = startX; x < right; x += effectiveMinorSpacing)
        {
            // 跳过主网格位置，避免重复绘制
            if (qAbs(fmod(x, effectiveMajorSpacing)) < 0.1)
                continue;
            painter->drawLine(x, top, x, bottom);
        }

        // 绘制水平次网格线
        for (qreal y = startY; y < bottom; y += effectiveMinorSpacing)
        {
            if (qAbs(fmod(y, effectiveMajorSpacing)) < 0.1)
                continue;
            painter->drawLine(left, y, right, y);
        }
    }

    // 绘制主网格（较粗、较深）
    QPen majorPen(m_majorGridColor, m_gridLineWidth + 1, Qt::SolidLine);
    painter->setPen(majorPen);

    // 计算主网格起始位置
    startX = qFloor(left / effectiveMajorSpacing) * effectiveMajorSpacing;
    startY = qFloor(top / effectiveMajorSpacing) * effectiveMajorSpacing;

    // 绘制垂直主网格线
    for (qreal x = startX; x < right; x += effectiveMajorSpacing)
    {
        painter->drawLine(x, top, x, bottom);
    }

    // 绘制水平主网格线
    for (qreal y = startY; y < bottom; y += effectiveMajorSpacing)
    {
        painter->drawLine(left, y, right, y);
    }

    painter->restore();
}

qreal SceneViewer::calculateEffectiveSpacing(qreal baseSpacing) const
{
    // 根据当前缩放因子调整网格间距，避免缩放时网格过密或过疏
    qreal scale = transform().m11(); // 获取水平缩放因子

    if (scale > 2.0)
    {
        return baseSpacing * scale / m_gridDensity;
    }
    else if (scale < 0.5)
    {
        return baseSpacing / (m_gridDensity * (1.0 / scale));
    }

    return baseSpacing;
}
